package test;

/** Parse comma-separated values (CSV), a common Windows file format.
 * Sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625
 * <p>
 * Inner logic adapted from a C++ original that was
 * Copyright (C) 1999 Lucent Technologies
 * Excerpted from 'The Practice of Programming'
 * by Brian W. Kernighan and Rob Pike.
 * <p>
 * Included by permission of the http://tpop.awl.com/ web site, 
 * which says:
 * "You may use this code for any purpose, as long as you leave 
 * the copyright notice and book citation attached." I have done so.
 * @author Brian W. Kernighan and Rob Pike (C++ original)
 * @author Ian F. Darwin (translation into Java and removal of I/O)
 * @author Ben Ballard (rewrote advQuoted to handle '""' and for readability)
 * @author Serge Sol ( changed data input from CSV-file instead of a string )
 */
import java.util.*;
//import java.io.FileNotFoundException;
import java.io.IOException;
//import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import java.io.BufferedReader;
import java.io.FileInputStream;
//import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;

class CSV {  

  public static final char DEFAULT_SEP = ',';
 // private RandomAccessFile csvFile;
  
  BufferedReader buf = null;
  
  private List <String>header= new ArrayList<String>();
  private List <String>line = new ArrayList<String>();
 // private int headerLength;

 // private long csvLength;
  private int length = -1; // when all csv file is processed has length of records. If -1 then csv file not fully parsed
  private int currentLine = 0; // number of line we are working with. Line count starts from 1 
  

  /** Construct a CSV parser, with the default separator (`,'). 
 * @throws IOException */
  public CSV(String inFile) throws IOException {
    this(inFile, DEFAULT_SEP);
  }

  /** Construct a CSV parser with a given separator. 
   * @param sep The single char for the separator (not a list of
   * separator characters)
   * @throws IOException 
   */
  public CSV(String inFile, char sep) throws IOException {
	// inHandle = new File(inFile);
	 System.out.println(inFile);
	// RandomAccessFile(inFile, "r");
	fieldSep = sep;
	//csvFile = new RandomAccessFile(inFile, "r");
	//csvLength = csvFile.length();
	//buf = new BufferedReader(new FileReader(inFile));
	InputStream inputStream = new FileInputStream(inFile);
	buf = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
	
	
	// read header
	header = parse(buf.readLine());
	/*header = parse(
			new String(buf.readLine().getBytes(),"UTF-8")
			);
	*/
	//header = parse(csvFile.readLine());
	//header = parse(csvFile.readUTF());
	
	
//	headerLength =header.size(); 
  }

  /** The fields in the current String */
  //protected List list = new ArrayList();

  /** the separator char for this parser */
  protected char fieldSep;
  
  private boolean stringIntertupted;

  public CSVLine nextLine() throws IOException {
	  //long filePointer;
	  //long len;
	  //lineParsed=false;
	  StringBuffer sb = new StringBuffer();
	  String sCurrentLine=null;
	  //filePointer = csvFile.getFilePointer();
	  //len = csvFile.length();
	  //if (filePointer == len) {length=currentLine; return null;}
	  
	  do {
		  try {
	    	 //sb.append(csvFile.readLine());
	    	 sCurrentLine=buf.readLine();
	    	 if (sCurrentLine == null) {
	    		 throw new Exception(" ====================================                  CSV Exception                          ===========================================");
	    		 //System.out.println("CSV analise end with length = " + length ); length=currentLine; return null;
	    		 }
	    	 
	    	 //sCurrentLine = new String(sCurrentLine.getBytes(),"UTF-8");
	    	//String.class.getConstructors();
	    	 sb.append(sCurrentLine);
			 // sb.append(csvFile.readUTF());
			 line = parse(sb.toString());
		  } catch (Exception e) {
			 length=currentLine;
			 System.out.println(e);
			 System.out.println("End with length = " + length );
			 return null;
		  }
	  } while (stringIntertupted); // while (line.size()<headerLength && !lineParsed); // (filePointer < csvLength);
	  //if (sCurrentLine == null) {System.out.println("CSV analise end with length = " + length ); length=currentLine; return null;}
	  currentLine++; 
	  //csvFile.readLine();
	  
	  
	  Map<String, String> fieldMap = new HashMap<String, String>();
	  Iterator<String> itLine = line.iterator();
	  Iterator<String> itHeader = header.iterator();
	  while (itLine.hasNext() && itHeader.hasNext()) {
	    //  System.out.println(it.next());
		  fieldMap.put(itHeader.next(), itLine.next());
	  }
	  
	 // CSVLine test  = new CSVLine();
	 // CSVLine test2 = new CSVLine(fieldMap, currentLine, filePointer, csvFile.getFilePointer()-filePointer);
	 // if (test == test2) {}
	  return new CSVLine(fieldMap, currentLine);
//	  return new CSVLine(fieldMap, currentLine, filePointer, csvFile.getFilePointer()-filePointer);

	  
	  //String[] line = new Array(headerLength);
	  //return line;
  }
  
  
  public boolean isReady () {
	  return (length>-1);
  }
  
  
  /** parse: break the input String into fields
   * @return java.util.Iterator containing each field 
   * from the original as a String, in order.
   */
  public List<String> parse(String line)
  {
	stringIntertupted = false ;
	List<String> list = new ArrayList<String>();
	StringBuffer sb = new StringBuffer();
    //list.clear();      // recycle to initial state
    int i = 0;

    if (line.length() == 0) {
      list.add(line);
      return list;
    }

    do {
            sb.setLength(0);
            if (i < line.length() && line.charAt(i) == '"')
                i = advQuoted(line, sb, ++i);  // skip quote
            else
                i = advPlain(line, sb, i);
            list.add(sb.toString());
      i++;
    } while (i < line.length());

    return list;
  }

  /** advQuoted: quoted field; return index of next separator */
  private int advQuoted(String s, StringBuffer sb, int i)
  {
  	stringIntertupted = true ;
    int j;
    int len= s.length();
        for (j=i; j<len; j++) {
            if (s.charAt(j) == '"' && j+1 < len) {
                if (s.charAt(j+1) == '"') {
                    j++; // skip escape char
                } else if (s.charAt(j+1) == fieldSep) { //next delimeter
                    j++; // skip end quotes
                    stringIntertupted = false ;
                    break;
                }
            } else if (s.charAt(j) == '"' && j+1 == len) { // end quotes at end of line
                break; //done
      }
      sb.append(s.charAt(j));  // regular character.
    }
    return j;
  }

  /** advPlain: unquoted field; return index of next separator */
  private int advPlain(String s, StringBuffer sb, int i)
  {
    int j;

    j = s.indexOf(fieldSep, i); // look for separator
        if (j == -1) {                 // none found
            sb.append(s.substring(i));
            return s.length();
        } else {
            sb.append(s.substring(i, j));
            return j;
        }
  }
  
  
  
}
